/* 
   ========================================================================
   Autor       : Tobi,Vladimir,Niron
   Dateiname   : vier_gewinnt.c
   Datum       : 06.05.2011
   Beschreibung: Hier sind alle Funktionsdefinitionen f\201r 4 Gewinnt zu finden
   Version     : 1.0
   ======================================================================== 
*/

#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include "header.h"


// Eine Position im Feld kann sein:
enum field {
   EMPTY = 0,
   PL1, // Spieler 1 setzen
   PL2  // Spieler 2 setzen
};
 
// Funktions return
enum result {
   BR, //Spielabbruch
   INV,  // ung\201ltige position
   USED, // position bereits gesetzt
   WON,  // finde 4er kette
   NE,   // nicht genug 4er kette nicht gefunden
   FULL  // alle Postionen auf Feld bereits gesetzt
};
 
 
const int field_char[3] = { ' ', 'O', '#' };
const int frame_char[2] = { '+', '-' };
const char *player_str[2] = { "CPU", "Spieler" };
 
enum field xy[WIDTH][HEIGHT]; // Spiel-Feld (breite x h\224he)
int xy_count = 0; // Anzahl der Positionen im Feld xy[][] setzen
 


//-------------------------------------------------------------------
// Beschreibung:
//    print xy[][] feld auf text-screen,
//    ix / Breite - vertical, iy / h\224he - horizontal,
//    x Zahlen oben und unten
void print_field(void)
{
   int ix, iy;
   system("cls");
   putchar('\n');
   
   system("cls");
   
   // oberste Zeile mit x Zahlen
   for (ix = 0; ix < WIDTH; ix++)
      printf(" %d", ix+1);
   putchar('\n');
 
   // Rahmen obere Zeile
   for (ix = 0; ix <= WIDTH * 2; ix++)
      putchar(frame_char[ix%2]);
   putchar('\n');
 
   for (iy = 0; iy < HEIGHT; iy++)
   {
      // eine iy linie
      putchar('|');
      for (ix = 0; ix < WIDTH; ix++)
      {
         putchar( field_char[ xy[ix][HEIGHT-iy-1] ] );
         putchar('|');
      }
      putchar('\n');
 
   }
 
   // Rahmen
   for (ix = 0; ix <= WIDTH * 2; ix++)
      putchar(frame_char[ix%2]);
   putchar('\n');
 
   // Unter Strich mit Anzahl x
   for (ix = 0; ix < WIDTH; ix++)
      printf(" %d", ix+1);
   putchar('\n');
 
   putchar('\n');
}//------------------------------------------------------------------



//------------------------------------------------------------------------
// Beschreibung: 
//    \201berpr\201fe if 0 <= ix < Breite und
//    \201berpr\201fe if 0 <= iy < H\224he und
//    \201berpr\201fe if xy position gesetzt ist von Player 1 (PL1) oder player zwei (PL2)
// Parameter:
//    int player - Spieler 1 (PL1) or Spieler 2 (PL2)
//    int ix - x Spalte
//    int iy - y position in x Spalte
int xy_pl(int player, int ix, int iy)
{
   return ix >= 0 && ix < WIDTH  &&
          iy >= 0 && iy < HEIGHT &&
          xy[ix][iy] == player;
}
//------------------------------------------------------------------------------



//--------------------------------------------------------------------------
// Beschreibung
//    setze gegebene x position, wenn sie noch frei ist
// parameters:
//    int player - Player 1 (PL1) or Player 2 (PL2)
//    int ix - x Spalte
// returns: ein enum Ergebniswert
//    INV  - ung\201ltige Position
//    USED - Position bereits gesetzt
//    WON  - 4er Kette gefunden
//    NE   - nicht genug 4er Kette nicht gefunden
enum result place(int player, int ix)
{
   int olru_cnt = 0; // oben links -> rechts untem
   int omum_cnt = 0; // oben in der mitte -> unten in der Mitte
   int mlmr_cnt = 0; // Mitte links -> Mitte rechts
   int orlu_cnt = 0; // oben rechts -> links unten
   int i, iy;
 
   // \201berpr\201fen ob Parameter ung\201ltig sind
   if ( ( player != PL1 && player != PL2 ) ||
        ix < 0 || ix >= WIDTH )
      return INV;
   // \201berpr\201fen ob es eine freie Postion in der Spalte gibt
   if ((iy=next_empty_y(ix)) == -1)
      return USED;
 
   // Setze Position
   xy[ix][iy] = player;
   xy_count++;
 
#define CHECK4(player, ix, iy, counter)   \
   for (i = 1; i <= 3; i++)               \
      if ( !xy_pl(player,ix,iy) )         \
         break;                           \
   counter += i - 1;
 
   // \232berpr\201fe 4 in einer Zeile
   CHECK4(player, ix-i, iy-i, olru_cnt);
   CHECK4(player, ix+i, iy+i, olru_cnt);
   CHECK4(player, ix,   iy-i, omum_cnt);
   CHECK4(player, ix,   iy+i, omum_cnt);
   CHECK4(player, ix-i, iy,   mlmr_cnt);
   CHECK4(player, ix+i, iy,   mlmr_cnt);
   CHECK4(player, ix+i, iy-i, orlu_cnt);
   CHECK4(player, ix-i, iy+i, orlu_cnt);
 
   // Pr\201fen ob eine vierer Kette vorhanden ist
   if ( olru_cnt > 2 ||
        omum_cnt > 2 ||
        orlu_cnt > 2 ||
        mlmr_cnt > 2 )
      return WON;
 
   return NE;
}//----------------------------------------------------

//--------------------------------------------------
// Beschreibung:
//    human Spieler spielt ein Zug
//    Erhalte Spaltennummer und Platz
// parameters:
//    int player - Spieler 1 (PL1) oder Spieler 2 (PL2)
enum result human_new_pos(int player)
{
   int new_x, c;
 
   // Erhalte Spalten nummer
   switch(player)
   {
		case 1:
                printf("%s, neue Position (1-%d): ",
                acBenutzernameEins, WIDTH );
                break;

        case 2:
                printf("%s, neue Position (1-%d): ",
                acBenutzernameZwei, WIDTH );
                break;
           
   }
   new_x = (c = getchar()) - '1';
   while (c != '\n')
      c = getchar();
 
   // \232berpr\201fe Spalten nummer
   printf("%i",new_x);
   if(new_x == 71 || new_x == 39)
   {
		return BR;
   }
   if ( new_x < 0 || new_x >= WIDTH )
      return INV;
 
   // Stelle
   return place(player, new_x);
}
//----------------------------------------------------------


//---------------------------------------------------------
// Beschreibung: 
//    computer Spieler spielt einen Zug
//    W\204hlt zuf\204llig spaltennummer und Platz
// parameters:
//    int player - Spieler 1 (PL1) oder Spieler 2 (PL2)
enum result computer_new_pos(int player)
{
   static int randomize = 1;
 
   // \201berpr\201fe ob Zufallsgenerator initialisiert wurde
   if (randomize)
   {
      // init Zufahlsgenerator
      srand(time(NULL));
      randomize = 0;
   }
 
   // Platz f\201r eine zuf\204llige Spalte
   return place(player, (double)rand() / RAND_MAX * WIDTH);
}
//------------------------------------------------------------------

//-----------------------------------------------------------------
// Beschreibung:
//   Ein Spieler spielt einen Zug
// Aufruf der Funktion f\201r Mensch oder Computer Gegner
// Parameters:
//    int player - Spieler 1 (PL1) oder Spieler 2 (PL2)
//    int human - 1 es ist ein Mensch, 0 es ist ein Computer


enum result play_new_pos(int player, int human)
{
  
    // Pr\201fe ob alle Positionen gesetzt sind
   if (xy_count == WIDTH*HEIGHT)
      return FULL;
 

   return human ?
      human_new_pos(player) :
      computer_new_pos(player);
}
/* 
   ======================================================================== 
   Funktion init_field()
   ======================================================================== 
*/
// Beschreibung:
//    initialisiere feld xy
void init_field(void)
{
   int ix, iy;
 
   for (ix = 0; ix < WIDTH; ix++)
      for (iy = 0; iy < HEIGHT; iy++)
         xy[ix][iy] = EMPTY;
 
   xy_count = 0;
}


/* 
   ======================================================================== 
   Funktion fourInARow()
   ======================================================================== 
*/
// Beschreibung:
//    Spiele 4 Gewinnt
int fourInARow(int iKi)
{
    
   enum result result;
   int human[2];
   int iZufall;

   switch(iKi)
   {
       case 0:
                   human[0] = 1;
                   human[1] = 1;
                   break;
           case 1:
                   srand (time(NULL));
                   iZufall =rand()%10000;
                   iZufall = iZufall%2;
                   switch(iZufall)
                   {
                       case 0:
                                   human[0] = 1;
                           human[1] = 0;
                                   break;
                           case 1:
                                   human[0] = 0;
                           human[1] = 1;

                   }
   }

   // W\204hle Spiel modus
   fflush(stdin);
   //select_modus(human);

   // initialisiere Feld
   init_field();
 
   // Spielen bis ein Spieler gewinnt oder unentschieden ist
   while (1)
   {
      //if (human[0])
         print_field();
 
      // Spieler 1 Runde
      do
      {
		  result = play_new_pos(PL1, human[0]);
		 if(result == INV)
		 {
			printf("\nung\201ltiger Zug !\n");
		 }
	  }
      while ( result == INV || result == USED );
	  
	  if(result == BR)
	  {
			system("cls");
			printf("Spiel wurde abgebrochen !\n");
			system("pause");
			return ABBRUCH;
	  }
      // \232berpr\201fe ob Spieler 1 gewonnen hat
      if (result == WON)
      {
         print_field();
         printf( "%s hat gewonnen!\n\n", acBenutzernameEins);
         system("pause");
		 return SIEG1;
         break;
      }
      else if (result == FULL)
         break;
 
      //Wenn (human[1])
         print_field();
 
      // Spieler 2 Runde
      do
         result = play_new_pos(PL2, human[1]);
      while ( result == INV || result == USED );
 
      // \232berpr\201fe ob Spieler 2 gewonnen hat
      if (result == WON)
      {
         print_field();
         printf( "%s hat gewonnen!\n\n", acBenutzernameZwei );
         system("pause");
		 return SIEG2;
         break;
      }
      else if (result == FULL)
         break;
   }
 
   // \232berpr\201fung auf Unentschieden
   if (result == FULL)
   {
      print_field();
      printf("Unentschieden...Das Spielbrett ist voll!!!");
	  system("pause");
	  return UNENTSCHIEDEN;
   }
}

/* 
   ======================================================================== 
   Funktion next_empty_y()
   ======================================================================== 
*/

int next_empty_y(int ix)
{
   int iy;

   for (iy = 0; iy < HEIGHT; iy++)
      if (xy[ix][iy] == EMPTY) // y Position leer?
         return iy;
 
   return -1; // alle y positionen gesetzt durch einen Spieler
}
